package LinkedList;

public class DoubleLinkedList {
    //头部节点
    private DoubleLinkedList.Node header;

    public DoubleLinkedList()
    {
        DoubleLinkedList.Node node = new DoubleLinkedList.Node();
        this.header = node;
    }

    /**
     * 链表尾部插入数据
     *
     * @param value int 插入的数据内容
     *
     * @return void
     **/
    public void tailInsert(int value)
    {
        DoubleLinkedList.Node lastNode = this.header;

        while (null != lastNode.getNext()) {
            lastNode = lastNode.getNext();
        }
        lastNode.setNext(new DoubleLinkedList.Node(value, lastNode));
    }

    /**
     * 链表头部插入数据
     *
     * @param value int 插入的数据内容
     *
     * @return void
     **/
    public void headInsert(int value)
    {
        DoubleLinkedList.Node newNode = new DoubleLinkedList.Node(value, this.header, this.header.getNext());
        this.header.getNext().setPrev(newNode);
        this.header.setNext(newNode);
    }

    /**
     * 删除一个数据
     *
     * @param value int 删除某个数据
     * @param count int 删除数据的数量
     *
     * @return int 删除数据的个数
     **/
    public int deleteValue(int value, int count)
    {
        int deleteCount = 0;
        DoubleLinkedList.Node lastNode = this.header.getNext();

        while (null != lastNode && deleteCount < count) {
            if (value == lastNode.getValue()) {
                lastNode.getPrev().setNext(lastNode.getNext());
                lastNode.getNext().setPrev(lastNode.getPrev());
                deleteCount++;
            }
            lastNode = lastNode.getNext();
        }
        return deleteCount;
    }

    /**
     * 修改一个数据
     *
     * @param search  int 查询的数据值
     * @param replace int 修改目标的数据值
     * @param count   int 需要修改多少个数据
     *
     * @return int 已修改的数据数量
     **/
    public int replaceValue(int search, int replace, int count)
    {
        int replaceCount = 0;
        DoubleLinkedList.Node lastNode = this.header.getNext();

        while (null != lastNode && replaceCount < count) {
            if (search == lastNode.getValue()) {
                lastNode.setValue(replace);
                replaceCount++;
            }
            lastNode = lastNode.getNext();
        }
        return replaceCount;
    }

    /**
     * 校验一个值是否存在
     *
     * @param value int 数据值
     *
     * @return boolean
     **/
    public boolean isExists(int value)
    {
        DoubleLinkedList.Node lastNode = this.header.getNext();

        while (null != lastNode) {
            if (value == lastNode.getValue()) {
                return true;
            }
            lastNode = lastNode.getNext();
        }
        return false;
    }

    /**
     * 查找一个值的位置
     *
     * @param value int 数据值
     *
     * @return int -1代表未找到
     **/
    public int getIndex(int value)
    {
        DoubleLinkedList.Node lastNode = this.header.getNext();
        int index = 0;

        while (null != lastNode) {
            if (value == lastNode.getValue()) {
                return index;
            }
            lastNode = lastNode.getNext();
            index++;
        }
        return -1;
    }

    /**
     * 打印链表
     *
     * @return void
     **/
    public void print()
    {
        DoubleLinkedList.Node lastNode = this.header.getNext();

        while (null != lastNode) {
            System.out.printf("%d\t", lastNode.getValue());
            lastNode = lastNode.getNext();
        }
        System.out.println();
    }

    protected class Node {
        //next指针域
        private DoubleLinkedList.Node next = null;
        //prev指针域
        private DoubleLinkedList.Node prev = null;
        //数据域
        private int value = 0;

        public Node(int value, DoubleLinkedList.Node prev, DoubleLinkedList.Node next)
        {
            this.next = next;
            this.value = value;
            this.prev = prev;
        }

        public Node(int value, DoubleLinkedList.Node prev)
        {
            this.value = value;
            this.prev = prev;
        }


        public Node(int value)
        {
            this.value = value;
            this.next = null;
        }

        public Node()
        {
        }

        public DoubleLinkedList.Node getNext()
        {
            return next;
        }

        public void setNext(DoubleLinkedList.Node next)
        {
            this.next = next;
        }

        public int getValue()
        {
            return value;
        }

        public void setValue(int value)
        {
            this.value = value;
        }

        public Node getPrev()
        {
            return prev;
        }

        public void setPrev(Node prev)
        {
            this.prev = prev;
        }
    }
}
